﻿using Microsoft.CSharp;
using System;
using System.CodeDom.Compiler;
using System.Collections.Generic;
using System.ComponentModel;
using System.Text;

namespace LittleBee.Utils
{
    public static class Utils
    {
        public static object? ChangeType(object value, Type targetType)
        {

            /*if (targetType.IsGenericType && targetType.GetGenericTypeDefinition() == typeof(Nullable<>))
            {
                NullableConverter nullableConverter = new NullableConverter(targetType);
                Type convertType = nullableConverter.UnderlyingType;
                return Convert.ChangeType(value, convertType);
            }*/
            if (value == null && targetType.IsGenericType)
            {
                return Activator.CreateInstance(targetType);
            }
            if (value == null)
            {
                return null;
            }
            if (targetType == value.GetType())
            {
                return value;
            }
            if (targetType.IsEnum)
            {
                if (value is string)
                {
                    return Enum.Parse(targetType, (value as string)!);
                }
                else
                {
                    return Enum.ToObject(targetType, value);
                }
            }
            if (!targetType.IsInterface && targetType.IsGenericType)
            {
                Type innerType = targetType.GetGenericArguments()[0];
                object? innerValue = ChangeType(value, innerType);
                return Activator.CreateInstance(targetType, new object[] { innerValue! });
            }
            if (value is string && targetType == typeof(Guid))
            {
                return new Guid((value as string)!);
            }
            if (value is string && targetType == typeof(Version))
            {
                return new Version((value as string)!);
            }
            if (!(value is IConvertible))
            {
                return value;
            }
            return Convert.ChangeType(value, targetType);
        }

        /// <summary>
        /// convert timestamp(ms) to datetime
        /// timestamp is the millisecond counts from 1970.1.1
        /// </summary>
        /// <param name="timeStamp">milliseconds which to convert</param>
        /// <returns>return datetime according to timestamp(ms)</returns>
        public static DateTime ConvertToDateTime(long timeStamp)
        {
            DateTime dateTimeStart = TimeZoneInfo.ConvertTime(new System.DateTime(1970, 1, 1), TimeZoneInfo.Local);
            return dateTimeStart.AddTicks(timeStamp);
        }

        /// <summary>
        /// Convert DateTime to Time stamp
        /// time stamp is the millisecond counts from 1970.1.1
        /// </summary>
        /// <param name="time"></param>
        /// <returns></returns>
        public static long ConvertToTimestamp(DateTime time)
        {
            DateTime dateTimeStart = TimeZoneInfo.ConvertTime(new System.DateTime(1970, 1, 1), TimeZoneInfo.Local);
            return (long)(time - dateTimeStart).Ticks;
        }


		/// <summary>
		/// encode code string to base64
		/// </summary>
		/// <param name="code_type">code type: utf8 ...</param>
		/// <param name="code">string code</param>
		/// <returns>base64 string of code</returns>
		public static string EncodeBase64(string code_type, string code)
		{
			string encode = "";
			byte[] bytes = Encoding.GetEncoding(code_type).GetBytes(code);
			try
			{
				encode = Convert.ToBase64String(bytes);
			}
			catch
			{
				encode = code;
			}
			return encode;
		}

		/// <summary>
		/// 解码, decode base64 string to string(code type: utf8 ...)
		/// </summary>
		/// <param name="code_type">code type: utf8 ...</param>
		/// <param name="code">base64 string code</param>
		/// <returns>string code(utf8 ...)</returns>
		public static string DecodeBase64(string code_type, string code)
		{
			string decode = "";
			byte[] bytes = Convert.FromBase64String(code);
			try
			{
				decode = Encoding.GetEncoding(code_type).GetString(bytes);
			}
			catch
			{
				decode = code;
			}
			return decode;
		}

		public static byte[] DecodeBase64(string code)
		{
			return Convert.FromBase64String(code);
		}

		public static string EncodeBase64(byte[] codes)
		{
			return Convert.ToBase64String(codes);
		}
	}
}
